import * as step from '@flow-step/step-toolkit'
import * as sinon from 'sinon';
import { expect } from 'chai'
import proxyquire from 'proxyquire'
import path from 'path'
import {checkCustomRuleDir} from '../lib/utils'


describe('checkCustomRuleDir', () => {

    it('should throw an error if customRuleDir is undefined', () => {
        expect(() => checkCustomRuleDir(undefined)).to.throw('customRuleDir is required when useCustomRule is true');
    });

    it('should throw an error if customRuleDir is an absolute path', () => {
        expect(() => checkCustomRuleDir('/absolute/path')).to.throw('customRuleDir /absolute/path is invalid. It should be a relative path without parent directory references.');
    });

    it('should throw an error if customRuleDir contains parent directory references', () => {
        expect(() => checkCustomRuleDir('../relative/path')).to.throw('customRuleDir ../relative/path is invalid. It should be a relative path without parent directory references.');
    });

    it('should throw an error if customRuleDir contains parent directory references-another form ', () => {
        expect(() => checkCustomRuleDir('relative/../path')).to.throw('customRuleDir relative/../path is invalid. It should be a relative path without parent directory references.');
    });

    it('should throw an error if customRuleDir is a file', () => {
        expect(() => checkCustomRuleDir('src/index.ts')).to.throw('customRuleDir src/index.ts is not a directory');
    });

    it('should return customRuleDir if it is a valid directory', () => {
        expect(checkCustomRuleDir('src')).to.equal('src');
    });
});



describe('setDependentFiles and copyDependency', () => {
    let sandbox: sinon.SinonSandbox;
    let extractStub: sinon.SinonStub;
    let debugStub: sinon.SinonStub;
    let fsStub: {
        existsSync: sinon.SinonStub;
        chmodSync: sinon.SinonStub;
        unlinkSync: sinon.SinonStub;
        copyFileSync: sinon.SinonStub;
    }

    beforeEach(() => {
        sandbox = sinon.createSandbox();
        extractStub = sandbox.stub(step.tool, 'extract').resolves('/extracted/path');
        debugStub = sandbox.stub(step, 'debug').resolves();
        fsStub = {
            existsSync: sandbox.stub().returns(false),
            chmodSync: sandbox.stub(),
            unlinkSync: sandbox.stub(),
            copyFileSync: sandbox.stub(),
        };
    });

    afterEach(() => {
        sandbox.restore();
    });

    it('should copy dependent files and set permissions', async () => {
        const targetDir = '/root/plugin';

        const setDependentFilesProxy = proxyquire('../src/utils', {
            fs: fsStub,
        }).setDependentFiles;

        const currentDir = path.join(__dirname,'..','src');

        await setDependentFilesProxy(targetDir);
        expect(fsStub.copyFileSync.calledTwice).to.be.true
        expect(debugStub.calledWith('set permission for diff to 755')).to.be.true
        expect(debugStub.calledWith(`p3c-2.2.1.tgz was extracted to /extracted/path`)).to.be.true
        expect(debugStub.calledWith(`copy ${path.join(currentDir,'diff')} to /root/plugin/diff`)).to.be.true
        expect(debugStub.calledWith(`copy ${path.join(currentDir,'plugin-base.jar')} to /root/plugin/plugin-base.jar`)).to.be.true
    });

    it('should throw an error if extraction fails', async () => {
        const targetDir = '/root/plugin';

        const setDependentFilesProxy = proxyquire('../src/utils', {
            fs: fsStub,
        }).setDependentFiles;

        const error = new Error('Extraction failed');
        extractStub.throws(error);

        try {
            await setDependentFilesProxy(targetDir);
        }catch (e:any){
            expect(e.message).to.equal(`failed to extract p3c-2.2.1.tgz to ${targetDir}: ${error}`)
        }
    });
});
